package com.itheima.health.security;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.util.Map;

public class MyFinalPasswordEncoder extends DelegatingPasswordEncoder {
    /**
     * Creates a new instance
     *
     * @param idForEncode         the id used to lookup which {@link PasswordEncoder} should be
     *                            used for {@link #encode(CharSequence)}
     * @param idToPasswordEncoder a Map of id to {@link PasswordEncoder} used to determine
     *                            which {@link PasswordEncoder} should be used for {@link #matches(CharSequence, String)}
     */
    private static final String PREFIX = "{";
    private static final String SUFFIX = "}";
    private Map<String, PasswordEncoder> idToPasswordEncoder;
    private PasswordEncoder defaultEncoder=new BCryptPasswordEncoder();
    public MyFinalPasswordEncoder(String idForEncode, Map<String, PasswordEncoder> idToPasswordEncoder) {
        super(idForEncode, idToPasswordEncoder);
        this.idToPasswordEncoder=idToPasswordEncoder;
    }

    public boolean matches(CharSequence rawPassword, String prefixEncodedPassword) {
        if(rawPassword == null && prefixEncodedPassword == null) {
            return true;
        }
        String id = extractId(prefixEncodedPassword);
        if (id==null){
            return defaultEncoder.matches(rawPassword,prefixEncodedPassword);
        }
        PasswordEncoder delegate = this.idToPasswordEncoder.get(id);
        if(delegate == null) {
            return NoOpPasswordEncoder.getInstance()
                    .matches(rawPassword, prefixEncodedPassword);
        }
        String encodedPassword = extractEncodedPassword(prefixEncodedPassword);
        return delegate.matches(rawPassword, encodedPassword);
    }
    private String extractId(String prefixEncodedPassword) {
        if (prefixEncodedPassword == null) {
            return null;
        }
        int start = prefixEncodedPassword.indexOf(PREFIX);
        if(start != 0) {
            return null;
        }
        int end = prefixEncodedPassword.indexOf(SUFFIX, start);
        if(end < 0) {
            return null;
        }
        return prefixEncodedPassword.substring(start + 1, end);
    }
    private String extractEncodedPassword(String prefixEncodedPassword) {
        int start = prefixEncodedPassword.indexOf(SUFFIX);
        return prefixEncodedPassword.substring(start + 1);
    }
}
